iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

Have fun! 新手也能打造的Javascript微型專案系列 第 20

Have fun! 新手也能打造的Javascript微型專案! Day20: 觀念跟語法老是忘記? 那寫個flash-card程式來幫助自己記憶吧!(中)

  • 分享至 

  • xImage
  •  
tags: ItIron2022 Javascript

前言

昨天我們做好了基本的ui以及簡單帶過了翻卡的原理,今天我們就要慢慢的加入js邏輯讓整個頁面可以順利地動起來,用到的技巧都是之前帶過的東西,相信並不會太困難,一起來挑戰吧!

Getting started

Step1: 需求釐清

要完成一個flash-card有幾個核心功能我們需要達成

  • 新增卡片資料

無疑是最重要、也是最優先要處理的功能,目前我們連唯一的一張卡片都是用假資料搞出來的。

  • 渲染出所有卡片

我們必須將存好的卡片資料一個一個照我們之前預設的結構渲染到畫面上,否則我們就沒有辦法像前一天示範的翻轉卡片了

  • 切換展示的卡片

點擊卡片會造成翻轉這個已經在渲染的部分解決了,但當你一次有複數張卡片時你便需要下方的左右箭頭來協助你做卡片的切換。

  • 清除所有卡片的資料

最後我們可以加入一個額外的功能去清除所有的卡片,讓使用者從頭開始!

我們今天會處理新增卡片以及渲染卡片的部分,就先從這兩個地方下手吧!

Step2: 新增卡片

在html/css的部分我們已經將新增卡片的表單以及對應的樣式都寫好了,我們只需要讓它在需要的時間點顯示即可,顯示的表單則有問題的輸入框、答案的輸入框、新增卡片的按鈕以及關閉整個視窗的按鈕,我們要做的事情就很簡單了!

選取需要的DOM元素
監聽新增卡片按鈕,點擊後顯示新增表單
監聽表單內的新增卡片按鈕,點擊後將輸入框的資訊存起來
關閉新增表單

至於存起來是要存到哪去呢? 當然你可以只用一個簡單的變數處理,但因為這種記憶卡的東西時不時就需要被打開,我們這邊用localStorage做比較長久的資料保存會更為恰當一些。

理解以上的步驟後我們就可以開始了,請你在js檔案中新增以下的程式碼

// 選取需要的DOM元素
const cardsContainer = document.getElementById("cards-container");
const showBtn = document.getElementById("show");
const hideBtn = document.getElementById("hide");
const questionEl = document.getElementById("question");
const answerEl = document.getElementById("answer");
const addCardBtn = document.getElementById("add-card");
const clearBtn = document.getElementById("clear");
const addContainer = document.getElementById("add-container");

// 從localStorage中取出卡片資料
const cardsData = getCardData();

// 取得localStorage卡片資料的函數,若資料不存在localStorage則設為空陣列
function getCardData() {
  const cards = JSON.parse(localStorage.getItem("cards"));
  return cards === null ? [] : cards;
}

// 將卡片資料存入localStorage
function setCardsData(cards) {
  localStorage.setItem("cards", JSON.stringify(cards));
  window.location.reload();
}

// 監聽新增卡片按鈕,點擊後顯示新增表單
showBtn.addEventListener("click", () => {
  addContainer.classList.add("show");
});

// 監聽表單內新增卡片按鈕,點擊後將新增的卡片資料存進localStorage
addCardBtn.addEventListener("click", () => {
  // 從兩個輸入框取值
  const question = questionEl.value;
  const answer = answerEl.value;
  
  // 若兩者的值不為空,則可以新增卡片
  if (answer.trim() && question.trim()) {
    // 建立新卡片並將新的卡片推進一開始的cardsData陣列中  
    const newCard = { question, answer };
    cardsData.push(newCard);
      
    // 清空當前輸入值      
    questionEl.value = "";
    answerEl.value = "";
    
    // 關閉輸入表單  
    addContainer.classList.remove("show");
    
    // 更新localStorage內的值  
    setCardsData(cardsData);
  }
});

到這邊我們就可以先測試一下目前的功能,我們需要達到以下的結果。

  1. 可以自由地開啟/關閉新增表單
  2. 新增卡片資料按鈕點擊後,能確實地在localStorage看到資料

為了方便測試,請你打開devtool並點選Application的tab,在左側選單則會有一個localStorage,你應該可以在裡面看到你剛剛隨便新增的卡片。

Step3: 渲染卡片

我們剛剛雖然順利的在localStorage新增了我們的卡片,但畫面上並沒有任何變化,我們需要在這個步驟完成卡片渲染的部分,一樣我們先釐清一下我們到底該做什麼。

我們需要一個createCard的函數將我們存在localStorage的資料渲染成我們指定結構的卡片,在這個函數中我們有幾個必須要做的事情

  1. 建立一個新的div元素並將class設為card(這樣才能套用我們預先寫好的樣式)
  2. 判斷卡片的位置,若為第一張卡片則加入active class(配合之後切換卡片功能)
  3. 將剛剛建立的div元素修改為我們翻牌的結構,並填入question & answer的值
  4. 在建立的div元素上加入監聽器,toggle show-answer讓卡片得以垂直翻轉
  5. 最終將新建立的div元素加到cardsContainer底下,呈現在畫面中

理解以上的部分後我們就可以在js中加入以下的內容

// 從localStorage渲染所有卡片
function createCards() {
  cardsData.forEach((item, index) => {
    createCard(item, index);
  });
}


// 建立卡片元素
function createCard(data, index) {
  const card = document.createElement("div");
  card.classList.add("card");

  if (index === 0) {
    card.classList.add("active");
  }

  card.innerHTML = `
    <div class="inner-card">
        <div class="inner-card-front">
          <p>${data.question}</p>
        </div>
        <div class="inner-card-back">
          <p>${data.answer}</p>
        </div>
    </div>
  `;

  card.addEventListener("click", () => {
    card.classList.toggle("show-answer");
  });

  cardsContainer.appendChild(card);
}


// 在js載入時便渲染所有卡片
createCards()

由於我們在新增卡片時有呼叫setCardsData函數,它新增資料後會重整整個頁面,因此新增卡片後你便會馬上在頁面上看到剛新增的卡片!到這邊我們最核心的功能就已經完成了,但現在卡片無法切換,這個部分就留在明天處理吧,你可以先思考以下的問題。

  1. 如何追蹤目前顯示的卡片
  2. 要怎麼切換成上一張/下一張卡片
  3. 要如何隱藏其他未顯示的卡片

其中2, 3很大一部分已經在css處理好了,你要做的就是用js加上需要的class而已!

總結

我們今天完成新增與顯示卡片的兩大功能,這種從localStorage抓資料做為預設值的手法相當常見,只要別忘記處理localStorage不存在值的情況就會是很好的手法!程式碼在處理的步驟雖然稍多,但邏輯並不算太複雜,對新手稍微困難但我認為是很好的練習,時間許可的話建議嘗試看看!

文章中的範例程式碼可以在這邊取得,歡迎自行取用

轉職Q & A

Danny,我到現在投遞履歷都沒收到任何回覆,你平常都是用哪一個平台進行投遞啊?

首先,當出現這樣的問題時,我覺得可能需要先思考一下你的履歷還有投遞的職缺是否真的都沒有問題 :D 我們這邊就先忽略這一點,直接回答一下你的問題吧!

  • 104/1111/518
    在台灣求職的話,這應該是最大宗的選擇了,但我通常不會在上面進行投遞,因為我很討厭他們的制式模板,另外我覺得他們的職務選擇非常的傳統,甚至沒有前端工程師可選wwww 但我會將其他地方做的履歷連結留在上方,即便只是這樣也時不時會收到一些聯繫,不無小補。

  • Yourator
    一個主打新創媒合的求職平台,許多新創甚至是部分外商的職缺都會在上面,履歷的面板近期也經過更新,算是用起來還蠻不錯的平台,若你的目標是新創公司的話那會是個很好的選擇,不過我當時使用時覺得職缺更新較慢,選擇會稍微少一些。

  • Cakeresume
    我個人蠻喜歡的一個平台,真有投遞的話基本上我是在Cakeresume上進行居多,他的履歷模板簡單好用,同時也可以用css自己客製化,不至於做出太醜的履歷,對於求職我覺得相當夠用。上面也有許多獵頭、人資會主動出擊,我認為觸及率算相當不錯,行有餘力的話可以填寫好完整的資料並做一些基本的技能測試,數據上是有提高一些履歷拜訪率的。

至於LinkedIn嘛...坦白說初次求職這個真的沒有幫到我什麼,沒有相關的經歷要在眾多profile中脫穎而出實在有些困難,因此雖然這是我目前求職的主力但針對第一次求職者來說我認為優先度可以放低一些,你自然可以好好經營你的LinkedIn帳號,對於未來會相當有幫助!

本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!


上一篇
Have fun! 新手也能打造的Javascript微型專案! Day19: 觀念跟語法老是忘記? 那寫個flash-card程式來幫助自己記憶吧!(上)
下一篇
Have fun! 新手也能打造的Javascript微型專案! Day21: 觀念跟語法老是忘記? 那寫個flash-card程式來幫助自己記憶吧!(下)
系列文
Have fun! 新手也能打造的Javascript微型專案30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言